﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using __ts.Core.Package;
using SevenZip;

namespace CCU.PackageBuilder
{
    public partial class MainForm : Form
    {
        delegate void SetProgressDelegate(ProgressEventArgs args);
        delegate void SetFileNameDelegate(FileNameEventArgs args);
        delegate void SetNoArgsDelegate();
        delegate void SetSettings(SevenZipCompressor compr);
        private static List<string[]> list = new List<string[]>();

        public MainForm()
        {
            InitializeComponent();
        }

        private void btnAddItem_Click(object sender, EventArgs e)
        {
            AddItemForm af = new AddItemForm();
            if (af.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                string[] tmp = new string[] { af.source, af.target, af.isFile ? "1" : "0" };
                list.Add(tmp);
                listView1.Items.Add(new ListViewItem(tmp));
            }
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            listView1.Items.Clear();
            list.Clear();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            this.tbPacketOutputPath.Text = "D:\\Publish";
            this.tbPacketName.Text = string.Format("server.test_1_0_0", DateTime.Now.ToString("yyyyMMdd"));
        }

        private void btnBuild_Click(object sender, EventArgs e)
        {
            if (listView1.Items.Count > 0)
            {
                pb_CompressWork.Style = ProgressBarStyle.Marquee;
                Thread worker = new Thread(new ThreadStart(Compress));
                worker.Start();
            }
            else
            {
                MessageBox.Show("操作终止！请先设置好更新包的内容项。");
            }
        }

        private void browsePacketOutputPath_Click(object sender, EventArgs e)
        {
            if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
            {
                tbPacketOutputPath.Text = folderBrowserDialog1.SelectedPath;
            }
        }

        void cmp_Compressing(object sender, ProgressEventArgs e)
        {
            pb_CompressProgress.Invoke(new SetProgressDelegate((args) =>
            {
                pb_CompressProgress.Increment(args.PercentDelta);
            }), e);
        }

        void cmp_FileCompressionStarted(object sender, FileNameEventArgs e)
        {
            l_CompressProgress.Invoke(new SetFileNameDelegate((args) =>
            {
                l_CompressProgress.Text = String.Format("Compressing \"{0}\"", e.FileName);
            }), e);
        }

        void cmp_CompressionFinished(object sender, EventArgs e)
        {
            l_CompressProgress.Invoke(new SetNoArgsDelegate(() =>
            {
                l_CompressProgress.Text = "Finished";
                pb_CompressWork.Style = ProgressBarStyle.Blocks;
                pb_CompressProgress.Value = 0;
            }));
        }

        private void Compress()
        {
            PackageCompressor pker = new PackageCompressor();
            if (IntPtr.Size == 8)
            {
                SevenZipCompressor.SetLibraryPath(@"7z64.dll");
            }
            else
            {
                SevenZipCompressor.SetLibraryPath(@"7z.dll");
            }
            SevenZipCompressor cmp = new SevenZipCompressor();
            cmp.Compressing += new EventHandler<ProgressEventArgs>(cmp_Compressing);
            cmp.FileCompressionStarted += new EventHandler<FileNameEventArgs>(cmp_FileCompressionStarted);
            cmp.CompressionFinished += new EventHandler(cmp_CompressionFinished);
            this.Invoke(new SetSettings((compressor) =>
            {
                compressor.ArchiveFormat = OutArchiveFormat.SevenZip;
                compressor.CompressionLevel = CompressionLevel.Normal;
                compressor.CompressionMethod = CompressionMethod.Default;
                compressor.VolumeSize = 0;
            }), cmp);

            string archFileName = "";
            this.Invoke(new SetNoArgsDelegate(() =>
            {
                archFileName = tbPacketOutputPath.Text.Trim(new char[] { '\\', '/' }) + "\\" + tbPacketName.Text.Trim()+".7rd";
            }));

            for (int i = 0; i < list.Count; i++)
            {
                string[] r = list[i];
                string directory = string.Empty;

                if (i == 0)
                    cmp.CompressionMode = CompressionMode.Create;
                else
                    cmp.CompressionMode = CompressionMode.Append;

                if (r[2].Trim() == "0")
                {
                    directory = r[0].Trim(new char[] { '\\', '/' });
                    cmp.PreserveDirectoryRoot = true;
                    pker.CompressDirectory(cmp, directory, archFileName);
                }
                else
                {
                    pker.CompressFilesEncrypted(cmp, archFileName, r[0]);
                }
            }
            if (!string.IsNullOrEmpty(tbBefore.Text))
            {
                addDefaultFile(cmp, archFileName, cmp.TempFolderPath + "extractBefore.bat", tbBefore.Text);
            }
            if (!string.IsNullOrEmpty(tbAfter.Text))
            {
                addDefaultFile(cmp, archFileName, cmp.TempFolderPath + "extractAfter.bat", tbAfter.Text);
            }
            addDefaultFile(cmp, archFileName, cmp.TempFolderPath + "package.xml", buildConfigXML());
        }

        private string buildConfigXML()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("<packageConfigs>\r\n")
                .Append("<extractpath>\r\n");

            for (int i = 0; i < list.Count; i++)
            {
                string dir = Path.GetFileName(list[i][0]);
                string dir2 = list[i][1];
                sb.Append(@"<")
                    .Append(dir)
                    .Append(">")
                    .Append(dir2)
                    .Append("</")
                    .Append(dir)
                    .Append(">\r\n");
            }
            sb.Append("</extractpath>\r\n")
            .Append("</packageConfigs>");

            return sb.ToString();
        }

        private void addDefaultFile(SevenZipCompressor cmp, string archFileName, string filePath, string content)
        {
            FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite);
            StreamWriter sw = new StreamWriter(fs, Encoding.Default);
            sw.Write(content);
            sw.Flush();
            sw.Dispose();
            cmp.CompressionMode = CompressionMode.Append;
            new PackageCompressor().CompressFilesEncrypted(cmp, archFileName, filePath);
        }

        private void btnPublish_Click(object sender, EventArgs e)
        {
            PublishForm pf = new PublishForm();
            pf.packagePath = tbPacketOutputPath.Text.Trim(new char[] { '\\', '/' }) + "\\" + tbPacketName.Text.Trim() + ".7rd";
            pf.ShowDialog();
        }
    }
}
